﻿using System;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Windows.Media;
using CommonBehaviors.Actions;
using Styx.CommonBot;
using Styx.Pathing;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using DayWalker.Managers;
using DayWalker.Specialisation;
using JetBrains.Annotations;
using DayWalker.Settings;
using DayWalker.Core;
using Styx;
using Styx.Common;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
using DayWalker.Helpers;
using Action = Styx.TreeSharp.Action;

namespace DayWalker
{
 
    partial class Daywalker
    {
      //  private RotationBase _currentRotation; // the current Rotation
       // private List<RotationBase> _rotations; // list of Rotations
                   
                   
            
      

      
       

        #region Nested type: LockSelector

        /// <summary>
        /// This behavior wraps the child behaviors in a 'FrameLock' which can provide a big performance improvement 
        /// if the child behaviors makes multiple api calls that internally run off a frame in WoW in one CC pulse.
        /// </summary>
        private class LockSelector : PrioritySelector
        {
            public LockSelector(params Composite[] children) : base(children)
            {
            }

            public override RunStatus Tick(object context)
            {
                using (StyxWoW.Memory.AcquireFrame())
                {
                    return base.Tick(context);
                }
            }
        }

        #endregion
        #region AutoTarget

        private static DateTime LastAutoTarget;

        public static Composite AutoTarget()
        {
            return new Action(delegate
            {
                if (!DayWalkerSettings.Instance.AutoTarget ||
                    LastAutoTarget > DateTime.Now)
                {
                    return RunStatus.Failure;
                }

                if (Me.CurrentTarget != null && Me.CurrentTarget.IsValid &&
                    !Helper.CurrentTargetAttackableNoLoS(50) &&
                    Helper.GetBestTarget() &&
                   Helper.UnitBestTarget != null &&
                 Helper.UnitBestTarget.IsValid &&
                    Me.CurrentTarget != Helper.UnitBestTarget)
                {
                    Helper.UnitBestTarget.Target();
                    Logging.Write(LogLevel.Diagnostic, "Switch to Best Unit");
                    LastAutoTarget = DateTime.Now + TimeSpan.FromMilliseconds(100);
                    return RunStatus.Failure;
                }

                if (Me.CurrentTarget == null &&
                 Helper.GetBestTarget() &&
                   Helper.UnitBestTarget != null &&
                  Helper.UnitBestTarget.IsValid)
                {
                    Helper.UnitBestTarget.Target();
                    Logging.Write(LogLevel.Diagnostic, "Target  Best Unit");
                    LastAutoTarget = DateTime.Now + TimeSpan.FromMilliseconds(100);
                    return RunStatus.Failure;
                }
                LastAutoTarget = DateTime.Now + TimeSpan.FromMilliseconds(100);
                return RunStatus.Failure;
            });
        }
    
        #endregion
        #region TargetMyPetTarget

        public static WoWUnit UnitAttackingMyPet;

       public static bool GetUnitAttackingMyPet()
        {
            UnitAttackingMyPet = null;
            //using (StyxWoW.Memory.AcquireFrame())
            {
                UnitAttackingMyPet = Helper.FarUnFriendlyUnits
                    .Where(Helper.BasicCheck)
                    .OrderByDescending(unit => unit.ThreatInfo.RawPercent)
                    .FirstOrDefault(
                        unit =>
                        unit.Combat &&
                        unit.GotTarget &&
                        (unit.CurrentTarget == Me ||
                         unit.CurrentTarget.CreatedByUnit == Me));
            }
            return Helper.BasicCheck(UnitAttackingMyPet);
        }

       public static Composite TargetMyPetTarget()
        {
            return new Decorator(
                ret =>
                !Helper.CurrentTargetAttackable(40) &&
                Me.Combat &&
                Helper.IsUsingAFKBot &&
                !Me.CurrentMap.IsArena &&
                !Me.CurrentMap.IsBattleground &&
                GetUnitAttackingMyPet(),
                new Action(delegate
                {
                    UnitAttackingMyPet.Target();
                    Logging.Write(LogLevel.Diagnostic, "TargetMyPetTarget {0}", UnitAttackingMyPet.SafeName);
                    return RunStatus.Failure;
                }));
        }

        #endregion
       #region Dismount

       public static Composite Dismount()
       {
           return new Decorator(
               ret =>
               Helper.IsUsingAFKBot &&
              Me.Combat || Me.CurrentMap.IsBattleground &&
               Me.Mounted &&
               !Me.IsFlying &&
               !Helper.IsMoving(Me) &&
               Helper.HasEnemyNear(Me, 30),
               new Action(delegate
               {
                   Mount.Dismount("Stuck on mount? Dismounting for combat.");
                   return RunStatus.Failure;
               }));
       }

       #endregion
       #region DeathRotation

       private const int RezMaxMobsNear = 0;
       private const int RezWaitTime = 10;
       private const int RezWaitDist = 20;

       private static string SelfRezSpell { get; set; }
       private static double MobsNearby { get; set; }
       private static DateTime NextSuppressMessage = DateTime.MinValue;

       public static Composite DeathRotation()
       {
           return new Decorator(
               req =>
               {
                   if (Me.IsAlive || Me.IsGhost)
                       return false;

                   List<string> hasSoulstone = Styx.WoWInternals.Lua.GetReturnValues("return HasSoulstone()",
                                                                   "hawker.lua");
                   if (hasSoulstone == null || hasSoulstone.Count == 0 ||
                       String.IsNullOrEmpty(hasSoulstone[0]) ||
                       hasSoulstone[0].ToLower() == "nil")
                       return false;

                   if (!DayWalkerSettings.Instance.AutoMove)
                   {
                       if (NextSuppressMessage < DateTime.Now)
                       {
                           NextSuppressMessage = DateTime.Now.AddSeconds(RezWaitTime);
                           Logging.Write(
                               "Suppressing {0} behavior since movement disabled...",
                               hasSoulstone[0]);
                       }
                       return false;
                   }

                   SelfRezSpell = hasSoulstone[0];
                   return true;
               },
               new Sequence(
                   new Action(
                       r =>
                       Logging.Write("Waiting up to {0} seconds for clear area to use {1}...",
                                     RezWaitTime, SelfRezSpell)),
                   new Wait(
                       RezWaitTime,
                       until =>
                       {
                           MobsNearby = Helper.CountEnemyNear(Me, RezWaitDist);
                           return MobsNearby <= RezMaxMobsNear || Me.IsAlive || Me.IsGhost;
                       },
                       new Action(r =>
                       {
                           if (Me.IsGhost)
                           {
                               Logging.Write(
                                   "Insignia taken or corpse release by something other than Singular...");
                               return RunStatus.Failure;
                           }

                           if (Me.IsAlive)
                           {
                               Logging.Write("Ressurected by something other than Singular...");
                               return RunStatus.Failure;
                           }

                           return RunStatus.Success;
                       })
                       ),
                   new DecoratorContinue(
                       req => MobsNearby > RezMaxMobsNear,
                       new Action(r =>
                       {
                           Logging.Write("Still {0} enemies within {1} yds, skipping {2}",
                                         MobsNearby, RezWaitDist, SelfRezSpell);
                           return RunStatus.Failure;
                       })
                       ),
                   new Action(
                       r =>
                       Logging.Write("Ressurrecting Singular by invoking {0}...", SelfRezSpell)),
                   new Action(r => Styx.WoWInternals.Lua.DoString("UseSoulstone()")),
                   new WaitContinue(1, until => Me.IsAlive || Me.IsGhost, new ActionAlwaysSucceed())
                   )
               );
       }
     
       #endregion
    }
}
